/** 
 * @(#)BeanTools.java 1.0.0 2015年10月8日 下午1:32:51  
 *  
 * Copyright © 2015 善林金融.  All rights reserved.  
 */ 

package com.common;

/**   
 *VO工具类(必须是有注解的对象) 
 *  
 * @author  HuYaHui
 * @version $Revision:1.0.0, $Date: 2015年10月8日 下午1:32:51 $ 
 */

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;

import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class BeanTools {
	private Log logger = LogFactory.getLog(getClass());
	private final String GET="get";
	private static BeanTools beanTools=new BeanTools();
	
	
	private BeanTools(){
	}

	/**
	 * 获取工具对象
	 * 2013-1-23 上午10:45:18 by HuYaHui 
	 * @return
	 */
	public static BeanTools getInstance(){
		return beanTools;
	}
	public String toString(Object obj){
		if(obj==null){
			return "";
		}
		//加载对象信息
		VO vo=BeanTools.getInstance().getFieldValuePairs(obj);
		Map<String,Object> fieldValueMap=vo.getMap();
		StringBuilder s=new StringBuilder();
		for(String fieldName:fieldValueMap.keySet()){
			s.append(fieldName).append(":").append(fieldValueMap.get(fieldName)).append("\n");
		}
		return s.toString();
	}

	/**
	 * 列名-->属性名
	 * 2013-8-8 下午2:27:31 by HuYaHui
	 * @param obj
	 * @return
	 */
	public VO columnNameToFieldName(Object obj){
		VO _vo=getVO(obj);
		VO rtnVO=new VO();
		rtnVO.setMap(VOcache.getColumnToFieldName(obj));
		rtnVO.setTableName(_vo.getTableName());
		rtnVO.setFieldNameList(_vo.getFieldNameList());
		return rtnVO;
	}
	
	/**
	 * 对象所有的属性
	 * 2013-1-23 下午1:15:47 by HuYaHui 
	 * @param obj
	 * @return
	 * @throws Exception
	 */
	public VO getAllField(Object obj){
		VO cacheVO=getVO(obj);
		return cacheVO;
	}
	
	
	/**
	 * 把对象所有非null的属性，转换为Map返回key:属性,value:值
	 * 2013-1-23 下午1:15:47 by HuYaHui 
	 * @param obj
	 * @return
	 * @throws Exception
	 */
	public VO getFieldValuePairs(Object obj){
		try {
			VO cacheVO=getVO(obj);
			Map<String,Object> fieldValueMap=new LinkedHashMap<String,Object>();
			Map<String, Method> methodMap=VOcache.getFieldNameToMethod(obj);
			for(String field_name:methodMap.keySet()){
				Object field_value=BeanUtilsExtends.getFieldValue(obj, field_name);
				if(field_value==null){
					continue;
				}
				fieldValueMap.put(field_name,field_value);
			}
			VO rtnVO=new VO();
			BeanUtilsExtends.copyProperties(rtnVO, cacheVO);
			rtnVO.setTableName(cacheVO.getTableName());
			rtnVO.setMap(fieldValueMap);
			return rtnVO;
		} catch (Exception e) {
			logger.error("getVOFieldMap出错", e);
		}
		return null;
	}
	
	/**
	 * 把对象所有列名和列对应的值
	 * 2013-9-11 上午11:35:29 by HuYaHui
	 * @param obj
	 * @return
	 * 		列名-->非null值
	 */
	public VO getColumnToNotNullValue(Object obj){
		try {
			//列名-->值
			Map<String,Object> columnTOValueMap=new LinkedHashMap<String,Object>();
			VO cacheVO=getVO(obj);
			//属性名-->数据库列名
			Map<String,Object> cacheFieldToColumn=cacheVO.getMap();
			for(String field_name:cacheFieldToColumn.keySet()){
				//获取属性的值
				Object method_value=getValue(obj, field_name);
				if(method_value==null){
					continue;
				}
				columnTOValueMap.put(cacheFieldToColumn.get(field_name)+"",method_value);
			}
			VO fieldMapVO=new VO();
			BeanUtilsExtends.copyProperties(fieldMapVO, cacheVO);
			fieldMapVO.setTableName(cacheVO.getTableName());
			fieldMapVO.setMap(columnTOValueMap);
			return fieldMapVO;
		} catch (Exception e) {
			logger.error("getVOColumnMap出错", e);
		}
		return null;
	}
	
	/**
	 * 把对象所有列名和列对应的值
	 * 2013-8-19 上午10:41:45 by HuYaHui
	 * @param obj
	 * @return
	 * 		列名-->值
	 */
	public VO getColumnToValue(Object obj){
		try {
			//列名-->值
			Map<String,Object> columnTOValueMap=new LinkedHashMap<String,Object>();
			VO cacheVO=getVO(obj);
			//属性名-->数据库列名
			Map<String,Object> cacheFieldToColumn=cacheVO.getMap();
			for(String field_name:cacheFieldToColumn.keySet()){
				//获取属性的值
				Object method_value=getValue(obj, field_name);
				columnTOValueMap.put(cacheFieldToColumn.get(field_name)+"",method_value);
			}
			VO fieldMapVO=new VO();
			BeanUtilsExtends.copyProperties(fieldMapVO, cacheVO);
			fieldMapVO.setTableName(cacheVO.getTableName());
			fieldMapVO.setMap(columnTOValueMap);
			return fieldMapVO;
		} catch (Exception e) {
			logger.error("getVOColumnMap出错", e);
		}
		return null;
	}
	
	private Object getValue(Object obj,String fieldName) throws Exception{
		return PropertyUtils.getProperty(obj, fieldName);
	}
	
	/**
	 * 获取VO对象
	 * 		(会缓存VO的tableName,get方法和所有属性)
	 * 2013-5-15 下午12:29:25 by HuYaHui
	 * @param obj
	 * @return
	 */
	private VO getVO(Object obj) {
		VO vo = VOcache.getObjToVO(obj);
		if (vo == null) {
			vo=new VO();
			//key:属性名,value:数据库列名
			Map<String,Object> map=new LinkedHashMap<String,Object>();
			//保存对象所有属性
			List<String> _fieldNameList=new ArrayList<String>();
			Class<?> cls = obj.getClass();
			Table table = cls.getAnnotation(Table.class);
			if(table!=null){
				String table_name=table.name();
				vo.setTableName(table_name);
			}
			
			Method[] methods = cls.getDeclaredMethods();
			Map<String, Method> methodMap = new LinkedHashMap<String, Method>();
			Map<String,Object> columnToFieldName=new LinkedHashMap<String, Object>();
			for (Method method : methods) {
				String method_name = method.getName();
				if (method_name.indexOf(GET) != 0) {
					//如果不是get方法
					continue;
				}
				//获取属性名
				String field_name = method_name.substring(3);
				field_name = field_name.substring(0, 1).toLowerCase()+ field_name.substring(1);
				//列名
				String column_name = "";
				Column column = method.getAnnotation(Column.class);
				if (column == null) {
					JoinColumn j=method.getAnnotation(JoinColumn.class);
					if(j!=null){
						column_name = j.name();
					}
					
				} else {
					column_name = column.name();
				}
				
				//如果是ID,每个表必须有主键
				Id id=method.getAnnotation(Id.class);
				if(id!=null){
					vo.setPrimaryKey(field_name);
					GeneratedValue gv=method.getAnnotation(GeneratedValue.class);
					if(gv!=null &&javax.persistence.GenerationType.IDENTITY.equals(gv.strategy())){
						//自动生成
						vo.setIdStrategy(javax.persistence.GenerationType.IDENTITY);
					}else if(gv!=null &&javax.persistence.GenerationType.SEQUENCE.equals(gv.strategy())){
						//使用序列
						vo.setIdStrategy(javax.persistence.GenerationType.SEQUENCE);
						SequenceGenerator seq=method.getAnnotation(SequenceGenerator.class);
						vo.setSeqName(seq.sequenceName());
					}
				}
				if(column_name!=null && !column_name.trim().equals("")){
					//保存到集合
					map.put(field_name, column_name);
					columnToFieldName.put(column_name, field_name);
				}
				//保存属性集合
				_fieldNameList.add(field_name);
				methodMap.put(field_name, method);
			}
			
			//保存所有属性名
			vo.setFieldNameList(_fieldNameList);
			//保存属性和数据库列名对应map
			vo.setMap(map);

			//对象全路径-->VO
			VOcache.setObjToVO(obj, vo);
			//列名-->属性名
			VOcache.setColumnToFieldName(obj, columnToFieldName);
			//属性名-->列名 
			VOcache.setFieldNameToColumn(obj, map);
			//属性名-->method对象
			VOcache.setFieldNameToMethod(obj, methodMap);
			//属性集合
			VOcache.setFieldList(obj, _fieldNameList);
		}
		return vo;
	}


}

